﻿using System.Collections.Generic;

namespace libbacktrack
{
    public partial class Backtrack
    {
        private void walk()
        {
            if (this.myGraph.MinDef() <= this.myGraph.NumVerDef)
            {
                this.isProcessing = true;
                walk(1);
            }
        }
        private void walk(int currentLevel)
        {
            if (this.isProcessing)
            {
                if (currentLevel >= this.myGraph.NumVerMain)
                {
                    if (this.myGraph.IsSemt())
                    {
                        if (!this.isRecurseAll)
                            this.isProcessing = false;
                        this.result += this.myGraph.Print(0);
                        this.result += "\n" + this.myGraph.Print(1)+"\n";
                        this.isSemt = true;
                    }
                    removeLabel(currentLevel - 1);
                }
                else
                {
                    List<int> availableLabels = new List<int>();
                    int start = 1, end = this.myGraph.NumVerTotal;
                    if (currentLevel == 1 && this.firstLabel != this.myGraph.NumVerTotal)
                    {
                        if (this.myGraph.GraphType == "wheel")
                            start = end; //optimization for wheel
                        else if (this.myGraph.GraphType == "doublefan")
                            start = this.firstLabel + 1; //optimization for doublefan
                    }
                    else if (this.pathStart != 0)
                    {
                        if (currentLevel == this.pathEnd)
                            start = this.pathLabel + 1; //remove possibility for reversed path labeling
                        else if (currentLevel == this.pathStart && start < end)
                            end = this.myGraph.NumVerTotal - 1; //no need to test last label as it'll be checked already on all previous cases
                    }
                    for (int i = start; i <= end; i++)
                        if (!this.labelVerUsed[i])
                            availableLabels.Add(i);
                    if (availableLabels.Count > 0)
                    {
                        for (int x = availableLabels.Count - 1; x >= 0; x--)
                        {
                            if (currentLevel == this.pathStart && this.pathStart != 0)
                                this.pathLabel = availableLabels[x];
                            if (this.myGraph.IsValidToLabel(currentLevel, availableLabels[x]))
                            {
                                setLabel(currentLevel, availableLabels[x]);
                                walk(currentLevel + 1);
                            }
                            if (!this.isProcessing)
                                break;
                        }
                    }
                    if (currentLevel != 1) { removeLabel(currentLevel - 1); }
                }
            }
        }
    }
}